package group_1.MultiSnake;

import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.opengl.texture.region.TextureRegion;

/**
 * Represents a part of the snake body.
 */
public class BodyPart extends Sprite implements SnakeConstants{
	
	private int growDirection;	// the direction that this bodypart should grow
	private float frontX;		// the front x-position of the bodypart
	private float frontY;		// the front y-position of the bodypart
	
	/**
	 * Constructor - construct a new vertical or horizontal bodypart
	 * 
	 * @param posX The start x-position of the bodypart
	 * @param posY The start y-position of the bodypart
	 * @param direction	The starting growdirection of the bodypart
	 * @param bodyTextureRegion	Stores the image representing the bodypart
	 */
	public BodyPart(float posX, float posY, int direction, TextureRegion bodyTextureRegion) {
		super(posX, posY, bodyTextureRegion);
		this.growDirection = direction;
		initBodyPart();
	}
	
	/**
	 * Constructor - construct a new corner body part
	 * 
	 * @param startX The start x-position of the bodypart
	 * @param startY The start y-position of the bodypart
	 * @param oldDirection The old direction of the snake
	 * @param newDirection The new direction of the snake
	 * @param bodyTextureRegion The image representing the bodypart
	 */
	public BodyPart(float posX, float posY, int oldDirection, int newDirection, TextureRegion bodyTextureRegion) {
		super(posX, posY, bodyTextureRegion);
		this.growDirection = newDirection;
		this.setHeight(BODY_THICKNESS);
		this.setWidth(BODY_THICKNESS);
		initBodyPart(oldDirection);
	}
	
	/**
	 * Initialize the rotation of the body part.
	 */
	private void initBodyPart() {
		switch(growDirection) {
		case UP:
		case DOWN:
			this.setRotation(90);
			break;
		}
		this.setWidth(0);
		this.changeLength(3);
	}
	
	/**
	 * Initialize the rotation of corner bodypart.
	 * 
	 * @param oldDirection The old direction of the snake. Used to determine how to rotate the body part.
	 */
	private void initBodyPart(int oldDirection){
		switch(oldDirection){
		case UP:
			if(growDirection == LEFT)
				this.setRotation(270);
			else if(growDirection == RIGHT)
				this.setRotation(180);
			break;
		case RIGHT:
			if(growDirection == DOWN)
				this.setRotation(270);
			break;
		case LEFT:
			if(growDirection == DOWN)
				this.setRotation(180);
			else if(growDirection == UP)
				this.setRotation(90);
		case DOWN:
			if(growDirection == RIGHT)
				this.setRotation(90);
		}
	}
	
	/**
	 * Change the length of the body part and position it depending on the current direction.
	 * @param change How much to change the body length.
	 * @return Return the new position.
	 */
	public void changeLength(float change) {
		this.setWidth(this.getWidth() + change);
		switch(growDirection) {
		case UP:
			moveY(-change);
			break;
		case LEFT:
			moveX(-change);
			break;
		}
	}
	
	/**
	 * Update front position of the body part
	 */
	private void updateFrontPosition() {
		switch(growDirection) {
		case UP:
		case LEFT:
			frontX = this.getX();
			frontY = this.getY();
			break;
		case DOWN:
			frontX = this.getX();
			frontY = this.getY()+getLength();
			break;
		case RIGHT:
			frontX = this.getX()+getLength();
			frontY = this.getY();
			break;
		}
	}
	
	/**
	 * Move body part in x-position
	 * @param movement How much to move in x-position.
	 */
	public void moveX(float movement) {
		this.setPosition(this.getX()+movement, this.getY());
	}
	
	/**
	 * Move body part in y-position
	 * @param movement
	 */
	public void moveY(float movement) {
		this.setPosition(this.getX(), this.getY()+movement);
	}
	
	/**
	 * Get the length of the body part
	 * @return Return the length of the body part
	 */
	public float getLength() {
		return this.getWidth();
	}
	
	/**
	 * Get the front x-position of the bodypart
	 * 
	 * @return The front x-position
	 */
	public float getFrontX() {
		updateFrontPosition();
		return frontX;
	}
	
	/**
	 * Get the front y-position of the bodypart
	 * 
	 * @return The front y-position of the bodypart
	 */
	public float getFrontY() {
		updateFrontPosition();
		return frontY;
	}
	
	/**
	 * Get the grow direction of the bodypart
	 * 
	 * @return The grow direction of the bodypart
	 */
	public int getGrowDirection() {
		return growDirection;
	}
}
